from PyQt4 import QtCore, QtGui
from guiqwt.builder import make
import sys
import serial
import time
import os

from collections import deque 

import UI
import numpy
import pickle
import SimpleTimeDomainView
from UI.MainWindow import Ui_MainWindow

from UI.CalDiag import Ui_CalDiag
from UI.ProbeCalibrateDiag import Ui_ProbeCalibrateDiag
from UI.SelectProbesDiag import Ui_SelectProbesDiag
from UI.SimplePlotDiag import Ui_SimplePlotDiag
import CommsMonitor


import threading

class SimplePlot(QtGui.QDialog, Ui_SimplePlotDiag):
    def __init__(self, ProbeCal, Buffer, Enables, Averaged):
        QtGui.QDialog.__init__(self)
        self.setupUi(self)
        
        self.curvewidget.register_all_curve_tools()
        self.curvewidget.plot.set_plot_limits(0,10000,0,100) 
        
        self.Buffer = Buffer
        self.ProbeCal = ProbeCal
        self.Timer = QtCore.QTimer()
        self.Timer.setInterval(1000) 
        self.Timer.setSingleShot(False)
        QtCore.QObject.connect(self.Timer, QtCore.SIGNAL("timeout()"), self.Tick)
        self.Timer.start()
        self.DataBuffers = {}
        self.Plots = {}
        self.times = deque([],10000)
        self.starttime = time.time()
        i = 0
        while i < len(Enables):
            if Enables[i] == True:
                self.DataBuffers[i] = deque([],10000)
                self.Plots[i] = make.curve([], [], color='b')
                self.curvewidget.plot.add_item(self.Plots[i])
        
            i+=1        
        
    def Tick(self):
        self.times.append(time.time()-self.starttime)
        #minx = self.times
        minx = self.times[0]
        maxx = self.times[len(self.times)-1]
        
        for probe in self.DataBuffers.keys():
            newTemp = self.ProbeCal[probe].GetTemp(self.Buffer[probe])
            
                
            self.DataBuffers[probe].append(newTemp)
            self.Plots[probe].set_data(self.times, self.DataBuffers[probe])
            self.Plots[probe].plot().replot()
            self.curvewidget.plot.set_plot_limits(minx,maxx*1.2,0,100) 
        
        
        


class SelectProbes(QtGui.QDialog, Ui_SelectProbesDiag):
    def __init__(self, ProbeCalObj):
        QtGui.QDialog.__init__(self)
        self.setupUi(self)
        

class CalObj:
    def __init__(self, ProbeName):
        self.ProbeName = ProbeName
        self.Temp1 = 0.0
        self.Raw1 = 0.0
        self.Temp2 = 100.0
        self.Raw2 = 1024.0
        
        self.Grad = 0.0
        self.Offset = 0.0
        self.Update()
        
    def Update(self):
        self.Grad = (1.0 * (self.Temp1 - self.Temp2)) / ((1.0* self.Raw1) - (1.0*self.Raw2))
        self.Offset = ((1.0 * self.Temp1 * self.Raw2)-(1.0 * self.Temp2 * self.Raw1))/(1.0*self.Raw2 - 1.0*self.Raw1)
        
    def GetTemp(self, RawData):
        return (self.Grad * RawData) + self.Offset

class Cal(QtGui.QDialog, Ui_CalDiag):
    def __init__(self, ProbeCalObj):
        QtGui.QDialog.__init__(self)
        self.setupUi(self)
        
        self.curvewidget.register_all_curve_tools()
        self.curve_item = make.curve([], [], color='b')
        self.curvewidget.plot.add_item(self.curve_item)
        self.curvewidget.plot.set_plot_limits(0,1024,-30,150) 
        
        self.ProbeCalObj = ProbeCalObj
        self.ProbeNameEdit.setText(self.ProbeCalObj.ProbeName)
        self.lineEdit.setText("""%0.2f C"""%self.ProbeCalObj.Temp1)
        self.lineEdit_2.setText("""%d """%self.ProbeCalObj.Raw1)
        self.lineEdit_3.setText("""%0.2f C"""%self.ProbeCalObj.Temp2)
        self.lineEdit_4.setText("""%d """%self.ProbeCalObj.Raw2)
        
        self.connect(self.ProbeNameEdit, QtCore.SIGNAL("editingFinished()"), self.UpdateName)
        
        self.connect(self.lineEdit, QtCore.SIGNAL("editingFinished()"), self.UpdateTemp1)
        
        self.connect(self.pushButton, QtCore.SIGNAL("clicked()"), self.UpdateSample1)
        self.connect(self.pushButton_2, QtCore.SIGNAL("clicked()"), self.UpdateSample2)
        
        self.DrawGraph()
        
        
    def UpdateName(self):
        self.ProbeCalObj.ProbeName = self.ProbeNameEdit.text()
    
    def UpdateTemp1(self):
        pass
        
    def UpdateSample1(self):
        self.ProbeCalObj.Raw1 = int(self.lineEdit_2.text())
        self.ProbeCalObj.Temp1 = float(self.lineEdit.text().replace("C",""))
        self.ProbeCalObj.Update()
        self.DrawGraph()
    
    def UpdateSample2(self):
        self.ProbeCalObj.Raw2 = int(self.lineEdit_4.text())
        self.ProbeCalObj.Temp2 = float(self.lineEdit_3.text().replace("C",""))
        self.ProbeCalObj.Update()
        self.DrawGraph()
        
    def DrawGraph(self):
        RawSamples = numpy.arange(0,1024)
        Grad = (1.0 * (self.ProbeCalObj.Temp1 - self.ProbeCalObj.Temp2)) / ((1.0* self.ProbeCalObj.Raw1) - (1.0*self.ProbeCalObj.Raw2))
        Offset = ((1.0 * self.ProbeCalObj.Temp1 * self.ProbeCalObj.Raw2)-(1.0 * self.ProbeCalObj.Temp2 * self.ProbeCalObj.Raw1))/(1.0*self.ProbeCalObj.Raw2 - 1.0*self.ProbeCalObj.Raw1)
        Data = (RawSamples * self.ProbeCalObj.Grad) + self.ProbeCalObj.Offset
        self.curve_item.set_data(RawSamples, Data)
        self.curve_item.plot().replot()
        

class CalibrateProbes(QtGui.QDialog, Ui_ProbeCalibrateDiag):
    def __init__(self, Buffer, ProbeCal):
        QtGui.QDialog.__init__(self)
        self.setupUi(self)
        
        self.Buffer = Buffer
        self.ProbeCal = ProbeCal
        self.Timer = QtCore.QTimer()
        self.Timer.setInterval(1000) 
        self.Timer.setSingleShot(False)
        QtCore.QObject.connect(self.Timer, QtCore.SIGNAL("timeout()"), self.Tick)
        self.Timer.start()
    
    def Tick(self):
        i = 0
        while i < len(self.Buffer):
            Data = self.Buffer[i]
            self.tableWidget.setItem(i, 0, QtGui.QTableWidgetItem("""%s"""%(self.ProbeCal[i].ProbeName)))
            self.tableWidget.setItem(i, 1, QtGui.QTableWidgetItem("""%.2f"""%(Data)))
            #self.tableWidget.setItem(i, 1, QtGui.QTableWidgetItem("""%.2f"""%(self.ProbeCal[i])))
            self.tableWidget.setItem(i, 2, QtGui.QTableWidgetItem("""%.2f"""%(self.ProbeCal[i].GetTemp(Data))))
            
            self.tableWidget.setCellWidget(i, 3, QtGui.QPushButton("Calibrate"))
            self.tableWidget.cellWidget(i, 3).uniqueId = """%d"""%i
            self.tableWidget.cellWidget(i, 3).clicked.connect(self.Calibrate)
            i = i + 1
    
    def Calibrate(self):
        self.CalDiag = Cal(self.ProbeCal[int(self.sender().uniqueId)])
        self.CalDiag.show()
        #int(self.sender().uniqueId)
        #self.ProbeCal[int(self.sender().uniqueId)] = 100

class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)    
        self.setupUi(self)
        self.PlotViews = []
        
        self.Buffer = [0,0,0,0,0,0]
        self.ProbeCal = []
        try:
            f = open("CalFile.dat","rb")
            while 1:
                try:
                    self.ProbeCal.append(pickle.load(f))
                except:
                    break
                    
            f.close()
        except:
            self.ProbeCal = [CalObj('1'), CalObj('2'), CalObj('3'), CalObj('4'), CalObj('5'), CalObj('6')]
        
        
        self.connect(self.actionCalibrate_Probes, QtCore.SIGNAL("triggered()"), self.CalibrateProbes)
        self.connect(self.pushButton_2, QtCore.SIGNAL("clicked()"), self.ToggleOutput)
        #self.connect(self.pushButton_3, QtCore.SIGNAL("clicked()"), self.Close)
        
        self.connect(self.pushButton, QtCore.SIGNAL("clicked()"), self.SelectProbesAction)
        
        self.CommsStatus = CommsMonitor.Status()
        self.CommsStatus.Run = True
        
        self.Output = [114]
        print os.listdir(os.getcwd())
        f = open('Port.txt','r')
        port = f.read()
        f.close()
        self.SerialObj = serial.Serial(port, 2400)
        self.SerialObj.setStopbits(2)
        self.SerialObj.setTimeout(2)
        
        self.commsthread = threading.Thread(target = CommsMonitor.GetData, args = (self.Buffer, self.CommsStatus, self.SerialObj))
        self.commsthread.start()
        
        self.SimplePlotViews = []
    
    def closeEvent(self, Event):
        f = open("CalFile.dat","wb")
        for Cal in self.ProbeCal:
            pickle.dump(Cal, f)
        f.close()
        
        print "Exiting"
        self.CommsStatus.Run = False
        
    
    def ToggleOutput(self):
        if self.Output == 133:
            self.Output = 114
            self.SerialObj.write(chr(self.Output))
        else:
            self.Output = 133
            self.SerialObj.write(chr(self.Output))
        print self.Output
    
    def CalibrateProbes(self):
        self.CalibrateDiag = CalibrateProbes(self.Buffer, self.ProbeCal)
        self.CalibrateDiag.show()
        
    def SelectProbesAction(self):
        self.GetProbesDiag = SelectProbes(self.ProbeCal)
        self.GetProbesDiag.show()
        self.connect(self.GetProbesDiag, QtCore.SIGNAL("accepted()"), self.OpenSimplePlotView)
        
    def OpenSimplePlotView(self):
        ProbeStates = [False, False, False, False,False, False]
        ProbeStates[0] = (2==self.GetProbesDiag.checkBox_1.checkState())
        ProbeStates[1] = (2==self.GetProbesDiag.checkBox_2.checkState())
        ProbeStates[2] = (2==self.GetProbesDiag.checkBox_3.checkState())
        ProbeStates[3] = (2==self.GetProbesDiag.checkBox_4.checkState())
        ProbeStates[4] = (2==self.GetProbesDiag.checkBox_5.checkState())
        ProbeStates[5] = (2==self.GetProbesDiag.checkBox_6.checkState())
        Averaged = (2==self.GetProbesDiag.checkBox_7.checkState())
        Diag = SimplePlot(self.ProbeCal, self.Buffer, ProbeStates, Averaged)
        Diag.show()
        self.SimplePlotViews.append(Diag)
    



app = QtGui.QApplication(sys.argv)
form = MainWindow()
form.show()
app.exec_()